package com.jwsoft.manager.core.integration.addressParse;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.base.common.vo.common.CommonVO;
import com.bifang.module.base.core.integration.CommonIntegration;
import com.jwsoft.manager.common.enums.AreaEnum;
import com.jwsoft.manager.common.vo.addressParse.Address;
import com.jwsoft.manager.common.vo.addressParse.AddressInfo;
import com.jwsoft.manager.common.vo.eduAddressTreeInitial.EduAddressTreeInitialVO;
import com.jwsoft.manager.core.dao.model.EduAddressTree;
import com.jwsoft.manager.core.dao.model.EduAddressTreeInitial;
import com.jwsoft.manager.core.dao.model.EduAddressTreeOriginal;
import com.jwsoft.manager.core.dao.service.EduAddressTreeInitialService;
import com.jwsoft.manager.core.dao.service.EduAddressTreeOriginalService;
import com.jwsoft.manager.core.dao.service.EduAddressTreeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SmartParse {
    @Autowired
    private AreaParse areaParse;

    @Autowired
    private EduAddressTreeOriginalService originalService;


    @Autowired
    private EduAddressTreeService addressTreeService;

    @Autowired
    private CommonIntegration commonIntegration;


    public AddressInfo parseAddressInfo(String text) {
        AddressInfo addressInfo = new AddressInfo();
        TextHolder textHolder = new TextHolder(text);
        List<EduAddressTreeInitialVO> parseNodeList = new ArrayList<>();
        // 解析地区址
        Address address = areaParse.parse(addressInfo, textHolder,parseNodeList);
        areaParse.parseAddressDetail(addressInfo , parseNodeList);
        //解析街道以下的数据
        String detail = parseDetail(addressInfo,address, parseNodeList, addressInfo.getDetail());
        //正则解析
        regularParseDetail(addressInfo,parseNodeList,detail);
//        log.warn("解析地址-"+text+"-5校验指针映射是否存在开始时间："+ DateUtil.current());
//        //校验指针映射是否存在
//        parseNodeList = checkMajorPointerExist(parseNodeList,addressInfo);
        //校验节点是否存在数据库中
        parseNodeList = checkAddressNodes(parseNodeList);
        addressInfo.setParseNodes(parseNodeList);
        return addressInfo;
    }

    private void regularParseDetail(AddressInfo addressInfo,List<EduAddressTreeInitialVO> parseNodeList, String detail) {
        String address = detail.replaceAll("\\s", "");
        //处理行政区类型
        //2.识别村/社区  village
        address = areaParse.parseVillage(address, addressInfo,parseNodeList);

        //3.识别 路/街 road
        address = areaParse.parseRoad(address, addressInfo,parseNodeList);

        //识别 路/街 roadNumber
        address = areaParse.parseRoadNumber(address, addressInfo,parseNodeList);

        //处理非行政类型  地址节点
        //4.识别小区，其他地址描述
        address = areaParse.parseResidential(address, addressInfo,parseNodeList);

        //5.识别楼房编号 几幢
        address = areaParse.parseHouseNumber(address, addressInfo,parseNodeList);

        //6.识别单元编号
        address = areaParse.parseUnitNumber(address, addressInfo,parseNodeList);

        //7.识别房间号
        address = areaParse.parseRoomNumber(address, addressInfo,parseNodeList);

        //8.其他
        areaParse.parseOther(address,addressInfo,parseNodeList);
    }

    private String parseDetail(AddressInfo addressInfo,Address address,List<EduAddressTreeInitialVO> parseNodeList,String detail){
        if(StringUtils.isBlank(detail)){
            return detail;
        }
        if(CollectionUtils.isEmpty(parseNodeList)){
            return detail;
        }
        if(address==null){
            throw new AppException("地址解析异常:parseDetail");
        }
        Boolean flag = false;

        if(StringUtils.isNotBlank(address.getAreaName()) && address.getAddressId() != null  && address.getAreaType()!=null){
            flag=true;
        }

        List<Address> addresseList=address.getChildren();
        if(CollectionUtils.isEmpty(addresseList)){
            // 如果 parseNodeList 中没有 areaType 为 "town" 且不存在 address的数据，把 address添加到 parseNodeList 中
            if (!parseNodeList.stream().anyMatch(item -> "town".equals(item.getAreaType()) && !address.getAddressId().equals(item.getAddressId())) && flag){
                EduAddressTreeInitialVO initialVO=new EduAddressTreeInitialVO();
                initialVO.setAreaName(address.getAreaName());
                //将父节点di设置为解析list最后一个id
                initialVO.setParentId(parseNodeList.get(parseNodeList.size()-1).getAddressId());
                initialVO.setAddressId(address.getAddressId());
                initialVO.setAreaType(address.getAreaType());
                initialVO.setSearchTerm(address.getSearchTerm());
                initialVO.setRate(address.getRate());
                parseNodeList.add(initialVO);
            }
            return detail;
        }
        addresseList = addresseList.stream()
                .sorted(Comparator.comparingInt(item -> -item.getAreaName().length()))
                .collect(Collectors.toList());
        Address childAddress = null;
        String retdetail=detail;
        for(Address item  : addresseList){
            List<String> nameList=new ArrayList<>();
            nameList.add(item.getAreaName());
            if(StringUtils.isNotBlank(item.getSearchTerm())){
                nameList.addAll(Arrays.stream(item.getSearchTerm().split("#"))
                        .collect(Collectors.toList()));

                nameList = nameList.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
            }
            String key="";
            for(String name:nameList){
                if(detail.startsWith(name)){
                    key=name;
                    break;
                }
            }
            if(StringUtils.isNotBlank(key)){
                childAddress=item;
                retdetail=detail.substring(key.length());
                EduAddressTreeInitialVO initialVO=new EduAddressTreeInitialVO();
                initialVO.setAreaName(item.getAreaName());
                //将父节点di设置为解析list最后一个id
                initialVO.setParentId(parseNodeList.get(parseNodeList.size()-1).getAddressId());
                initialVO.setAddressId(item.getAddressId());
                initialVO.setAreaType(item.getAreaType());
                initialVO.setSearchTerm(item.getSearchTerm());
                initialVO.setRate(item.getRate());
                parseNodeList.add(initialVO);
                areaParse.checkMajorPoint(addressInfo, initialVO.getAddressId(), parseNodeList);
                flag = true;
                break;
            }
        }
        if(childAddress!=null&&StringUtils.isNotBlank(retdetail)){
            return parseDetail(addressInfo,childAddress,parseNodeList,retdetail);
        }

        // 如果 parseNodeList 中没有 areaType 为 "town" 且不存在 address的数据，把 address添加到 parseNodeList 中
        if (!parseNodeList.stream().anyMatch(item -> "town".equals(item.getAreaType()) && !address.getAddressId().equals(item.getAddressId())) && flag){
            EduAddressTreeInitialVO initialVO=new EduAddressTreeInitialVO();
            initialVO.setAreaName(address.getAreaName());
            //将父节点di设置为解析list最后一个id
            initialVO.setParentId(parseNodeList.get(parseNodeList.size()-1).getAddressId());
            initialVO.setAddressId(address.getAddressId());
            initialVO.setAreaType(address.getAreaType());
            initialVO.setSearchTerm(address.getSearchTerm());
            initialVO.setRate(address.getRate());
            parseNodeList.add(initialVO);
        }
        return retdetail;
    }
    /**
     * 校验映射指针是否存在
     * 使用指针映射，必须保证指针映射id在参数表中存在e
     * 并且指针映射的数据所对的id也必须在参数表存在
     * 如：婺城区下同创路  需要指向到 婺城区罗店镇下的同创路
     * 两个同创路都需要在参数表中存在，否则无法使用指针映射
     *
     * @param parseNodeList
     * @param addressInfo
     */
    private List<EduAddressTreeInitialVO> checkMajorPointerExist(List<EduAddressTreeInitialVO> parseNodeList, AddressInfo addressInfo) {
        List<EduAddressTreeInitialVO> list = new ArrayList<>();
        Integer lastMajorIndex = -1;
        Long defaultMajor = 0L;
        EduAddressTreeOriginal original = new EduAddressTreeOriginal();
        //判断节点是否在参数表存在,并且映射指针不为空时
        for (EduAddressTreeInitialVO initialVO : parseNodeList) {
            EduAddressTreeOriginal eduAddressTreeOriginal = originalService.getById(initialVO.getAddressId());
            if (eduAddressTreeOriginal != null && !defaultMajor.equals(eduAddressTreeOriginal.getMajorPointer())){
                lastMajorIndex = parseNodeList.indexOf(initialVO);
                original = eduAddressTreeOriginal;
            }
        }
        if (lastMajorIndex == -1){
            return parseNodeList;
        }
        //根据指针映射id获取上级链路数据，没有表示映射的节点不存在
        List<EduAddressTreeOriginal> originalLinkList
                = originalService.getAllLinkByOriginalId(original.getMajorPointer());
        if (CollectionUtil.isEmpty(originalLinkList)){
            return parseNodeList;
        }
        //表示存在这条数据有被映射过,改变下个节点的parentId
        if (parseNodeList.size() - 1 >= lastMajorIndex){
            list = Convert.toList(EduAddressTreeInitialVO.class, originalLinkList);
            if (parseNodeList.size() - 1 != lastMajorIndex){
                //改变下个节点父id
                parseNodeList.get(lastMajorIndex+1).setParentId(original.getMajorPointer());
                list.addAll(parseNodeList.subList(lastMajorIndex+1, parseNodeList.size()));
            }
            for (EduAddressTreeInitialVO initialVO : list) {
                //修正节点后 设置省市县数据到addressInfo
                if (initialVO.getAreaType().equals(AreaEnum.province.getType())){
                    addressInfo.setProvince(initialVO.getAreaName());
                    addressInfo.setProvinceId(initialVO.getAddressId());
                    addressInfo.setProvinceCode(initialVO.getAreaCode());
                }
                if (initialVO.getAreaType().equals(AreaEnum.city.getType())){
                    addressInfo.setCity(initialVO.getAreaName());
                    addressInfo.setCityId(initialVO.getAddressId());
                    addressInfo.setCityCode(initialVO.getAreaCode());
                }
                if (initialVO.getAreaType().equals(AreaEnum.district.getType())){
                    addressInfo.setDistrict(initialVO.getAreaName());
                    addressInfo.setDistrictId(initialVO.getAddressId());
                    addressInfo.setDistrictCode(initialVO.getAreaCode());
                }
                if (initialVO.getAreaType().equals(AreaEnum.town.getType())){
                    addressInfo.setTown(initialVO.getAreaName());
                    addressInfo.setTownId(initialVO.getAddressId());
                    addressInfo.setTownCode(initialVO.getAreaCode());
                }
            }

        }
        return list;
    }

    /**
     * 将解析的地址节点进行校验修正每个 addressId
     * @param parseNodeList
     * @return 返回地址链信息
     */
    public List<EduAddressTreeInitialVO> checkAddressNodes(List<EduAddressTreeInitialVO> parseNodeList) {
        //校验参数：是否去tree表查询数据  1去树表查询 0 去初始化表查询
        CommonVO addressParseCheck = new CommonVO();
        addressParseCheck.setParamKey("TREE_OR_INITIAL_FLAG");
        String treeOrInitialFlag = commonIntegration.getValueByKey(addressParseCheck);
        if (StringUtils.isBlank(treeOrInitialFlag)) {
            treeOrInitialFlag = BoolEnum.TRUE.getType();
        }
        int i = 0;
        for (EduAddressTreeInitialVO treeInitial : parseNodeList) {
            treeInitial.setExistInDB(BoolEnum.FALSE.getType());
            if (treeOrInitialFlag.equals(BoolEnum.TRUE.getType())) {
                if (treeInitial.getAddressId() != null) {
                    EduAddressTree treeNode = addressTreeService.getById(treeInitial.getAddressId());
                    if (treeNode != null) {
                        BeanUtil.copyProperties(treeNode, treeInitial);
                        treeInitial.setIsLastNode(treeNode.getLastNode());
                        treeInitial.setIsLeafNode(treeNode.getLeafNode());
                        treeInitial.setExistInDB(BoolEnum.TRUE.getType());
                    }
                }
                if (BoolEnum.FALSE.getType().equalsIgnoreCase(treeInitial.getExistInDB())) {
                    QueryWrapper<EduAddressTree> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda()
                            .eq(EduAddressTree::getParentId, treeInitial.getParentId())
                            .eq(EduAddressTree::getAreaName, treeInitial.getAreaName());
                    List<EduAddressTree> treeList = addressTreeService.list(queryWrapper);
                    if (!CollectionUtils.isEmpty(treeList)) {
                        BeanUtil.copyProperties(treeList.get(0), treeInitial);
                        treeInitial.setIsLastNode(treeList.get(0).getLastNode());
                        treeInitial.setIsLeafNode(treeList.get(0).getLeafNode());
                        treeInitial.setExistInDB(BoolEnum.TRUE.getType());
                    }
                }
                if (BoolEnum.TRUE.getType().equalsIgnoreCase(treeInitial.getExistInDB())) {
                    // 改变下一个节点的id
                    if (i < parseNodeList.size() - 1) {
                        parseNodeList.get(i + 1).setParentId(treeInitial.getAddressId());
                    }
                }
                i++;
            }
        }
        return parseNodeList;
    }
}
